package com.guoxin.hashmap;

import java.util.Map;
import java.util.Objects;

/**
 * @author guoxin
 * @date 2019/7/31
 */
public class MyHashMap7 {

    //初始容量
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    //最大容量
    static final int MAXIMUM_CAPACITY = 1 << 30;

    //默认扩容因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * 在a期间取消对一个(拆分)bin进行树化的bin计数阈值
     * 调整操作。应该小于TREEIFY_THRESHOLD，且at
     * 最多6个网格与收缩检测下删除。
     */
    static final int UNTREEIFY_THRESHOLD = 6;
    /**
     * 可将箱子装箱的最小表容量。
     * (否则，如果一个bin中有太多节点，则会调整表的大小。)
     * 应至少达到4 * TREEIFY_THRESHOLD以避免冲突
     * 在调整大小和树化阈值之间
     */
    static final int MIN_TREEIFY_CAPACITY = 64;


    /**
     * Basic hash bin node, used for most entries.  (See below for
     * TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
     */
    static class Entry<K, V> implements Map.Entry<K, V> {
        final int hash;
        final K key;
        V value;
        Entry<K, V> next;

        Entry(int hash, K key, V value, Entry<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public final K getKey() {
            return key;
        }

        @Override
        public final V getValue() {
            return value;
        }

        @Override
        public final String toString() {
            return key + "=" + value;
        }

        @Override
        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        @Override
        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        @Override
        public final boolean equals(Object o) {
            if (o == this) {
                return true;
            }
            if (o instanceof Map.Entry) {
                Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
                return Objects.equals(key, e.getKey()) &&
                        Objects.equals(value, e.getValue());
            }
            return false;
        }
    }

    static int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
}
